// 运算单元
// 运算单元包含LI,ADD,SUB,AND,OR,LSH(左移),RSH(有符号右移),RSHU(无符号右移)

module ALU (
    input [15:0] a,
    input [15:0] b,
    input [3:0] ALUC,
    output reg [15:0] ALU_out,
    output wire z
);
    wire [15:0] s_ADDSUB;

    wire [15:0] s_LI  = {{8{1'b0}}, b[7:0]};
    wire [15:0] s_NOT = ~a;
    wire [15:0] s_AND = a & b;
    wire [15:0] s_OR  = a | b;

    wire [15:0] s_LSH = a << b;
    wire [15:0] s_RSH = {a[15],a[14:0] >> b};
    wire [15:0] s_RSHU= a >> b;
    // wire [15:0] s_XOR = a ^ b;
    assign z = (ALU_out == 15'h0)? 1'b1:1'b0;
    
    always @(*) begin
        case (ALUC[2:0])
            3'b000:ALU_out = s_ADDSUB;
            3'b001:ALU_out = s_LI;
            3'b010:ALU_out = s_NOT;
            3'b011:ALU_out = s_AND;
            3'b100:ALU_out = s_OR;
            3'b101:ALU_out = s_LSH;
            3'b110:ALU_out = s_RSH;
            3'b111:ALU_out = s_RSHU;
            default: ALU_out = {16{1'bx}};
        endcase
    end

    //add
    addsub16 u_addsub16(
    	.a   (a   ),
        .b   (b   ),
        .sub (ALUC[3] ),
        .s   (s_ADDSUB   )
    );
    
    
endmodule

module addsub16 (
    input [15:0] a,b,
    input sub,
    output wire [15:0] s
);

    assign s = a + (b^{32{sub}}) + sub;
    
endmodule